terraform_remote_stateをまとめてみた
こんにちは!AWS事業本部コンサルティング部のたかくに(@takakuni_)です。
今回は、Terraformで使用されるterraform_remote_state
をまとめてみようと思います。
terraform_remote_stateとは
terraform_remote_state
とは、一言でいうと、「別フォルダのtfstateファイルのoutputを参照するdataブロック」です。
フォルダ間の値のやり取りで使う便利な機能で私も愛用しています。
詳しい使い方は、以下ブログで紹介されているので合わせてご覧いただければと思います。
ハブを作ろう!
terraform_remote_state
を使うにあたり、気をつけるポイントとして「どのフォルダがどのtfstateを参照しているか」という問題があります。
とっても便利ですが、作りすぎると参照先を迷走する時がたまにあります。
たとえば、以下のようなフォルダ構成があるとします。
また、terraform apply
はenvironment/production/alb
などのフォルダ単位で行うとします。
.
├── environment
│ ├── production
│ │ ├── README.md
│ │ ├── alb
│ │ │ ├── data.tf
│ │ │ ├── main.tf
│ │ │ ├── output.tf
│ │ │ ├── variables.tf
│ │ │ └── terraform.tfvars
│ │ ├── ec2
│ │ │ ├── data.tf
│ │ │ ├── main.tf
│ │ │ ├── output.tf
│ │ │ ├── variables.tf
│ │ │ └── terraform.tfvars
│ │ ├── security_group
│ │ │ ├── data.tf
│ │ │ ├── main.tf
│ │ │ ├── output.tf
│ │ │ ├── variables.tf
│ │ │ └── terraform.tfvars
│ │ ├── vpc
│ │ │ ├── data.tf
│ │ │ ├── main.tf
│ │ │ ├── output.tf
│ │ │ ├── variables.tf
│ │ │ └── terraform.tfvars
このフォルダ構成の場合、以下のように各フォルダごとにterraform_remote_state
を定義する必要があります。
# 配置するVPC、サブネットのIDを取得したい
data "terraform_remote_state" "vpc" {
backend = "s3"
config = {
bucket = "terraform-state-XXXXXXXXXXXX"
key = "production/vpc/terraform.tfstate"
region = "ap-northeast-1"
}
}
# ALBのSecurity Group IDを取得したい
data "terraform_remote_state" "security_group" {
backend = "s3"
config = {
bucket = "terraform-state-XXXXXXXXXXXX"
key = "production/security_group/terraform.tfstate"
region = "ap-northeast-1"
}
}
# ターゲットグループに登録するインスタンスIDを取得したい
data "terraform_remote_state" "ec2" {
backend = "s3"
config = {
bucket = "terraform-state-XXXXXXXXXXXX"
key = "production/ec2/terraform.tfstate"
region = "ap-northeast-1"
}
}
# 配置するVPC、サブネットのIDを取得したい
data "terraform_remote_state" "vpc" {
backend = "s3"
config = {
bucket = "terraform-state-XXXXXXXXXXXX"
key = "production/vpc/terraform.tfstate"
region = "ap-northeast-1"
}
}
# EC2のSecurity Group IDを取得したい
data "terraform_remote_state" "security_group" {
backend = "s3"
config = {
bucket = "terraform-state-XXXXXXXXXXXX"
key = "production/security_group/terraform.tfstate"
region = "ap-northeast-1"
}
}
# 配置するVPC、サブネットのIDを取得したい
data "terraform_remote_state" "vpc" {
backend = "s3"
config = {
bucket = "terraform-state-XXXXXXXXXXXX"
key = "production/vpc/terraform.tfstate"
region = "ap-northeast-1"
}
}
ご覧の通り、各ファイルごとに必要なterraform_remote_state
ブロックが異なっていることわかります。まとめると以下の通りです。
- alb:「ec2」、「security_group」、「vpc」のtfstate
- ec2:「security_group」、「vpc」のtfstate
- security_group:「vpc」のtfstate
- vpc:必要なし
個人的には許容範囲ですが、構成が大きくなるほどより参照が複雑になります。
そこで、terraform_remote_stateを一箇所にまとめ、参照先の一元化を行います。
やってみた
フォルダ構成の変更
はじめに、以下のようにterraform_remote_state用にフォルダを作成します。
.
├── environment
│ ├── production
│ │ ├── README.md
│ │ ├── alb
│ │ │ ├── data.tf
│ │ │ ├── main.tf
│ │ │ ├── output.tf
│ │ │ ├── variables.tf
│ │ │ └── terraform.tfvars
│ │ ├── ec2
│ │ │ ├── data.tf
│ │ │ ├── main.tf
│ │ │ ├── output.tf
│ │ │ ├── variables.tf
│ │ │ └── terraform.tfvars
│ │ ├── security_group
│ │ │ ├── data.tf
│ │ │ ├── main.tf
│ │ │ ├── output.tf
│ │ │ ├── variables.tf
│ │ │ └── terraform.tfvars
│ │ ├── vpc
│ │ │ ├── data.tf
│ │ │ ├── main.tf
│ │ │ ├── output.tf
│ │ │ ├── variables.tf
│ │ │ └── terraform.tfvars
│ │ ├── remote_state
│ │ │ ├── data.tf
│ │ │ ├── output.tf
terraform_remote_stateの収集
次に、environment/production/remote_state/data.tf
で、すべてのterraform_remote_stateを収集します。
# environment/production/alb/
data "terraform_remote_state" "alb" {
backend = "s3"
config = {
bucket = "terraform-state-XXXXXXXXXXXX"
key = "production/alb/terraform.tfstate"
region = "ap-northeast-1"
}
}
# environment/production/ec2/
data "terraform_remote_state" "ec2" {
backend = "s3"
config = {
bucket = "terraform-state-XXXXXXXXXXXX"
key = "production/ec2/terraform.tfstate"
region = "ap-northeast-1"
}
}
# environment/production/security_group/
data "terraform_remote_state" "security_group" {
backend = "s3"
config = {
bucket = "terraform-state-XXXXXXXXXXXX"
key = "production/security_group/terraform.tfstate"
region = "ap-northeast-1"
}
}
# environment/production/vpc/
data "terraform_remote_state" "vpc" {
backend = "s3"
config = {
bucket = "terraform-state-XXXXXXXXXXXX"
key = "production/vpc/terraform.tfstate"
region = "ap-northeast-1"
}
}
outputで再出力
最後に、environment/production/remote_state/outputs.tf
で収集したterraform_remote_stateをまとめて再出力します。
output "production" {
value = {
# vpc
vpc_id = data.terraform_remote_state.vpc.outputs.vpc_id
subnet_1a = data.terraform_remote_state.vpc.outputs.subnet_1a
subnet_1c = data.terraform_remote_state.vpc.outputs.subnet_1c
# security_group
sg_id_ec2 = data.terraform_remote_state.security_group.outputs.security_group_id_ec2
sg_id_alb = data.terraform_remote_state.security_group.outputs.security_group_id_alb
# ec2
web_a = data.terraform_remote_state.ec2.outputs.ec2_id_a
web_c = data.terraform_remote_state.ec2.outputs.ec2_id_c
# alb
alb_dns = data.terraform_remote_state.alb.outputs.alb_dns
}
}
もたらす効果
他のディレクトリは、environment/production/remote_state/
のみを参照することで他フォルダのterraform_remote_stateの参照が完結します。
各ディレクトリごとに定義していた、terraform_remote_state
に対するコード量の減少と、各ディレクトリの値を一元管理できるメリットがあります。
data "terraform_remote_state" "env" {
backend = "s3"
config = {
bucket = "terraform-state-XXXXXXXXXXXX"
key = "production/remote_state/terraform.tfstate"
region = "ap-northeast-1"
}
}
まとめると、各種フォルダに必要なtfstateが以下のように変化します。
「どこに何があるの?」から「とりあえず、remote_stateをみる」に変化します。
As Is
- alb:「ec2」、「security_group」、「vpc」のtfstate
- ec2:「security_group」、「vpc」のtfstate
- security_group:「vpc」のtfstate
- vpc:必要なし
To Be
- alb:「remote_state」のtfstate
- ec2:「remote_state」のtfstate
- security_group:「remote_state」のtfstate
- vpc:「remote_state」のtfstate
※vpcに関してはつけてもつけなくても良いです。個人的には、個別管理は煩雑さを招くため定義する派です。
参照
参考までに参照方法は以下の通りです。
Mapで出力しているため参照名が長いですが、文字列型で出力すれば少し短くできるかと思います。
resource "aws_instance" "web_1a" {
ami = var.ami_id
instance_type = "t2.micro"
subnet_id = data.terraform_remote_state.env.outputs.production.subnet_1a
security_groups = [
data.terraform_remote_state.env.outputs.production.security_group_id_ec2
]
}
参考記事
公式
DevelopersIO
おわりに
以上、「terraform_remote_stateをまとめてみた」でした。
terraform_remote_state
はとても便利ですが、管理も大変なので今回みたいな手法を使うと楽になれるかと思います。
この記事がどなたかの参考になれば幸いです。
以上、AWS事業本部コンサルティング部のたかくに(@takakuni_)でした!